package cn.daniellee.plugin.pm.component;

import cn.daniellee.plugin.pm.PartnerMission;
import com.google.gson.*;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import net.skinsrestorer.api.SkinsRestorerAPI;
import net.skinsrestorer.api.property.IProperty;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;

import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.*;

/**
 * 物品生成实用类
 */
public class ItemGenerator {

	public static boolean disableSkullLoad = false;

	private static Field PROFILE_FIELD;

	public static ItemStack getItem(String name, List<String> lore, String m, int durability) {
		Material material = Material.getMaterial(m.toUpperCase());
		if (material == null) material = Material.STONE;
		ItemStack itemStack = new ItemStack(material);
		itemStack.setDurability((short) durability);
		ItemMeta itemMeta = itemStack.getItemMeta();
		if (itemMeta != null) {
			itemMeta.setDisplayName(name.replace("&", "§"));
			if (lore != null && !lore.isEmpty()) {
				for (int i = 0; i < lore.size(); i++) lore.set(i, lore.get(i).replace("&", "§"));
				itemMeta.setLore(lore);
			}
			itemStack.setItemMeta(itemMeta);
		}
		return itemStack;
	}

	public static ItemStack getSkullItem(String owner, String texture, String name, List<String> lore) {
		Material material = Material.getMaterial("PLAYER_HEAD");
		if (material == null) material = Material.getMaterial("SKULL_ITEM");
		ItemStack itemStack = new ItemStack(Objects.requireNonNull(material));
		itemStack.setDurability((short) 3);
		SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta();
		if (skullMeta != null) {
			if (texture != null && !"".equals(texture)) {
				GameProfile profile = new GameProfile(UUID.randomUUID(), null);
				PropertyMap propertyMap = profile.getProperties();
				if (propertyMap != null) {
					propertyMap.put("textures", new Property("textures", texture));
					try {
						if (PROFILE_FIELD == null) {
							PROFILE_FIELD = skullMeta.getClass().getDeclaredField("profile");
							PROFILE_FIELD.setAccessible(true);
						}
						PROFILE_FIELD.set(skullMeta, profile);
					} catch (NoSuchFieldException | IllegalAccessException e) {
						PartnerMission.getInstance().getLogger().info("[PartnerMission]Player skull load failed.".replace("&", "§"));
					}
				}
			} else if (!disableSkullLoad) skullMeta.setOwningPlayer(Bukkit.getOfflinePlayer(owner));
			skullMeta.setDisplayName(name.replace("&", "§"));
			if (lore != null && !lore.isEmpty()) {
				for (int i = 0; i < lore.size(); i++) lore.set(i, lore.get(i).replace("&", "§"));
				skullMeta.setLore(lore);
			}
			itemStack.setItemMeta(skullMeta);
		}
		return itemStack;
	}

	public static String getPlayerTexture(String name) {
		if (PartnerMission.getInstance().hasSkinsRestorer()) {
			SkinsRestorerAPI skinsRestorerAPI = SkinsRestorerAPI.getApi();
			String skinName = skinsRestorerAPI.getSkinName(name);
			IProperty property = skinsRestorerAPI.getSkinData(skinName != null ? skinName : name);
			if (property != null) return property.getValue();
		}
		try {
			URL idUrl = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
			InputStreamReader idReader = new InputStreamReader(idUrl.openStream());
			String id = new JsonParser().parse(idReader).getAsJsonObject().get("id").getAsString();
			URL textureUrl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + id);
			InputStreamReader textureReader = new InputStreamReader(textureUrl.openStream());
			JsonObject textureProperty = new JsonParser().parse(textureReader).getAsJsonObject().get("properties").getAsJsonArray().get(0).getAsJsonObject();
			return textureProperty.get("value").getAsString();
		} catch (Exception ignored) {
			PartnerMission.getInstance().getLogger().info(("[PartnerMission]Player texture load field, Name: " + name).replace("&", "§"));
		}
		return null;
	}
}
